
/*
    PointMesh.m

    A PointMesh takes an array of points in three dimensional space and renders
    them as surface in space space using a Renderman bilinear patch mesh.

    You may freely copy, distribute, and reuse the code in this example.
    NeXT disclaims any warranty of any kind, expressed or implied, as to its
    fitness for any particular use.
*/

#import "Graph.h"

@implementation PointMesh

- init {
    self = [super init];
    color = NX_COLORWHITE;
    return self;
}

- free {
    free(points);
    return [super free];
}

/*
 * This copies ther given points into a 2D array that is formatted correctly
 * for the RiPatchMesh() call we use to render the patch (below).
 */
- setPointsX:(float *)x y:(float *)y z:(float *)z
	minX:(float)minX minY:(float)minY minZ:(float)minZ
	maxX:(float)maxX maxY:(float)maxY maxZ:(float)maxZ
	numU:(int)numU numV:(int)numV {
    int i;
    int totalPoints = numU * numV;

    uCount = numU;
    vCount = numV;
    free(points);
    points = NXZoneMalloc([self zone], totalPoints * sizeof(RtPoint));

    for (i = 0; i < totalPoints; i++) {
	points[i][0] = x[i];
	points[i][1] = y[i];
	points[i][2] = z[i];
    }
    return self;
}

/*
 * This method is called whenever the shape needs to render itself (its
 * analogous to View's drawSelf:: method).  The patch renders itself by
 * setting the surface type and the color, and then emitting one big bilinear
 * patch mesh containing all our data points.
 */
- renderSelf:(RtToken)context {
    static RtColor rgbColor;
    
    RiSurface("plastic", RI_NULL);
    NXConvertColorToRGB(color, &rgbColor[0], &rgbColor[1], &rgbColor[2]);
    RiColor(rgbColor);
    RiPatchMesh(RI_BILINEAR, uCount, RI_NONPERIODIC, vCount, RI_NONPERIODIC, RI_P, points, RI_NULL);
    return self;
}

- setColor:(NXColor)newColor {
    color = newColor;
    return self;
}

- (NXColor)color {
    return color;
}

@end
